﻿using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 玩家控制系统
/// 策略模式
/// </summary>
public class PlayerController : MonoBehaviour {
    #region field
    private Rigidbody mRig;
    private Transform mTrans;
    private Animator ani;
    private List<IAction> actions;
    private float floorLevelFlag;//用于判断碰撞位置在下方的标志
    private float yDev;//碰撞器y轴坐标的偏移量
    public PlayerAttr mva = new PlayerAttr();

    #endregion
    #region mono method

    private void Awake()
    {
        floorLevelFlag = -GetComponent<CapsuleCollider>().height * transform.localScale.y / 6f;
        yDev = GetComponent<CapsuleCollider>().center.y;

        mva.OnLookDirChange += RoToForward;//监听方向。换向旋转
        ani = GetComponentInChildren<Animator>();
        mRig = GetComponent<Rigidbody>();
        mTrans = transform.GetChild(0).transform;

        actions = new List<IAction>(new IAction[]{
            new WalkAct(this),
            new JumpAct(this),
            new FlyAct(this),
            new ShotAct(this)});

        foreach (var a in actions)//初始化各个行为
        {
            a.Init();
        }
    }

    private void FixedUpdate()
    {
        foreach (var a in actions)
        {
            a.GetAction();
        }
        UpdataAnimator();
    }

    private void OnCollisionStay(Collision collision)
    {
        if (TouchFloor(collision))
            mva.IsGround = true;
        // else
        //     mva.isGround = false;
        // print("stay");
    }

    private void OnCollisionExit(Collision collision)
    {
        //print(mRig.velocity.y);

         mva.IsGround = false;
    }

    public IAction GetAction<T>() where T:IAction
    {
        foreach (var a in actions)
        {
            if (a is T)
            {
                return a;
            }
        }
        return null;
    }
    #endregion

    public void AddAction(IAction action)
    {
        actions.Add(action);
        action.Init();
    }

    #region normal method

    /// <summary>
    /// 接触位置判断
    /// y坐标差值在[low,hight]内为true 。point-position
    /// </summary>
    private bool TouchLeveL(Collision collision, float low, float hight)
    {

        foreach (var p in collision.contacts)
        {
            print(p.normal);
            float incre = (p.point - Position()).y;
            if (incre <= hight && incre >= low)//位置低于标志位则为触底
            {
                return true;

            }
        }
        return false;
    }

    /// <summary>
    /// 接触法线向上
    /// </summary>
    /// <param name="collision"></param>
    /// <returns></returns>
    private bool TouchFloor(Collision collision)
    {
        //print(collision.contacts.Length);
        foreach (var p in collision.contacts)
        {
            if (p.normal.y > 0.8f)//位置低于标志位则为触底
            {
                //print("t");
                return true;
            }
        }
        //print("f");
        return false;

    }
    /// <summary>
    /// 更新动画机
    /// </summary>
    private void UpdataAnimator()
    {
        ani.SetBool("isGround", mva.IsGround);
        ani.SetBool("isWalking", mva.isWalking);
        ani.SetBool("isHolding", mva.IsHolding);
        ani.SetBool("isFlying", mva.isFlying);
    }
    /// <summary>
    /// 转身
    /// </summary>
    /// <param name="left"></param>
    public void RoToForward(bool left)
    {
        if (left)
        {
            mTrans.DORotate(Vector3.up * -90, 0.5f);
        }
        else
        {
            mTrans.DORotate(Vector3.up * 90, 0.5f);

        }
    }

    /// <summary>
    /// 经过偏移修正后的人物中心坐标
    /// </summary>
    /// <returns></returns>
    private Vector3 Position()
    {
        Vector3 result = mTrans.position;
        result.y += yDev;
        return result;
    } 
    #endregion
}
